package com.yuhuihui.common.utils;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * BigDecimal工具类
 *
 * @author yuhh
 * @date 2022-08-10 17:40:09
 */
public class BigDecimalUtil {

    public final static BigDecimal NEGATIVE_ONE = new BigDecimal("-1");

    public final static BigDecimal HUNDRED = new BigDecimal("100");

    /**
     * 获取该数的相反数
     *
     * @param number 需要转换的数字
     * @return {@link BigDecimal }
     * @author yuhh
     * @date 2022-08-10 17:40:59
     */
    public static BigDecimal getOppositeNumber(BigDecimal number){
        return notNull(number).multiply(NEGATIVE_ONE);
    }

    /**
     * 相减
     *
     * @param values 需要相减的值
     * @return {@link BigDecimal }
     * @author yuhh
     * @date 2022-09-05 18:16:56
     */
    public static BigDecimal subtraction(BigDecimal... values){
        if (values.length == 0) {
            return BigDecimal.ZERO;
        }
        if (values.length == 1){
            return notNull(values[0]);
        }
        BigDecimal result = notNull(values[0]);
        for (int i = 1, l = values.length; i < l; i++){
            result = result.subtract(notNull(values[i]));
        }
        return result;
    }

    /**
     * 相加
     *
     * @param values 需要相加的值
     * @return {@link BigDecimal }
     * @author yuhh
     * @date 2022-08-31 18:40:04
     */
    public static BigDecimal addition(BigDecimal... values){
        if (values.length == 0) {
            return BigDecimal.ZERO;
        }
        if (values.length == 1){
            return notNull(values[0]);
        }
        BigDecimal result = BigDecimal.ZERO;
        for (BigDecimal value : values) {
            result = result.add(notNull(value));
        }
        return result;
    }

    /**
     * 两数相除
     *
     * @param v1    被除数
     * @param v2    除数
     * @param scale 保留小数位
     * @return {@link BigDecimal }
     * @author yuhh
     * @date 2022-08-10 17:41:09
     */
    public static BigDecimal division(BigDecimal v1, BigDecimal v2, int scale){
        return division(v1, v2, scale, RoundingMode.HALF_UP);
    }

    /**
     * 两数相除
     *
     * @param v1           被除数
     * @param v2           除数
     * @param scale        保留小数位
     * @param roundingMode 保留模式
     * @return {@link BigDecimal }
     * @author yuhh
     * @date 2022-08-10 17:41:13
     */
    public static BigDecimal division(BigDecimal v1, BigDecimal v2, int scale, RoundingMode roundingMode){
        return notNull(v1).divide(notNull(v2), scale, roundingMode);
    }

    /**
     * 如果除数为null或为0，则返回0
     *
     * @param v1    被除数
     * @param v2    除数
     * @param scale 保留小数位
     * @return {@link BigDecimal }
     * @author yuhh
     * @date 2022-08-10 17:41:16
     */
    public static BigDecimal divisionIgnoreZero(BigDecimal v1, BigDecimal v2, int scale){
        if (BigDecimalUtil.isEqualsZero(notNull(v2))){
            return BigDecimal.ZERO;
        }
        return BigDecimalUtil.division(v1, v2, scale);
    }

    /**
     * 两数相乘
     *
     * @param v1    被乘数
     * @param v2    乘数
     * @param scale 保留小数位
     * @return {@link BigDecimal }
     * @author yuhh
     * @date 2022-08-10 17:41:20
     */
    public static BigDecimal multiply(BigDecimal v1, BigDecimal v2, int scale){
        return multiply(v1, v2, scale, RoundingMode.HALF_UP);
    }

    /**
     * 两数相乘
     *
     * @param v1           被乘数
     * @param v2           乘数
     * @param scale        保留小数位
     * @param roundingMode 保留模式
     * @return {@link BigDecimal }
     * @author yuhh
     * @date 2023-08-10 18:14:41
     */
    public static BigDecimal multiply(BigDecimal v1, BigDecimal v2, int scale, RoundingMode roundingMode){
        return notNull(v1).multiply(notNull(v2)).setScale(scale, roundingMode);
    }

    /**
     * 是否大于等于0
     *
     * @param v 需要判断的值
     * @return boolean true：是；false：否
     * @author yuhh
     * @date 2022-08-10 17:41:27
     */
    public static boolean isGreaterAndEqualsZero(BigDecimal v){
        int r = notNull(v).compareTo(BigDecimal.ZERO);
        return r > 0 || r == 0;
    }

    /**
     * v1是否大于等于v2
     *
     * @param v1 左边的值
     * @param v2 右边的值
     * @return boolean true：是；false：否
     * @author yuhh
     * @date 2022-08-10 17:41:33
     */
    public static boolean isGreaterAndEquals(BigDecimal v1, BigDecimal v2){
        int r = notNull(v1).compareTo(notNull(v2));
        return r > 0 || r == 0;
    }

    /**
     * v1是否大于v2
     *
     * @param v1 左边的值
     * @param v2 右边的值
     * @return boolean true：是；false：否
     * @author yuhh
     * @date 2022-08-10 17:41:40
     */
    public static boolean isGreater(BigDecimal v1, BigDecimal v2){
        int r = notNull(v1).compareTo(notNull(v2));
        return r > 0;
    }

    /**
     * v1是否等于0
     *
     * @param v1 需比较的值
     * @return boolean true：是；false：否
     * @author yuhh
     * @date 2022-08-10 17:41:45
     */
    public static boolean isEqualsZero(BigDecimal v1){
        int r = notNull(v1).compareTo(BigDecimal.ZERO);
        return r == 0;
    }

    /**
     * v1是否大于0
     *
     * @param v1 需比较的值
     * @return boolean true：是；false：否
     * @author yuhh
     * @date 2022-08-10 17:41:50
     */
    public static boolean isGreaterZero(BigDecimal v1){
        int r = notNull(v1).compareTo(BigDecimal.ZERO);
        return r > 0;
    }

    /**
     * v1是否等于v2
     *
     * @param v1 左边的值
     * @param v2 右边的值
     * @return boolean true：是；false：否
     * @author yuhh
     * @date 2022-08-10 17:41:53
     */
    public static boolean isEquals(BigDecimal v1, BigDecimal v2){
        int r = notNull(v1).compareTo(notNull(v2));
        return r == 0;
    }

    /**
     * 得到该数的正数
     *
     * @param v 需要转换的数字
     * @return {@link BigDecimal }
     * @author yuhh
     * @date 2022-08-10 17:41:57
     */
    public static BigDecimal getPositiveNumber(BigDecimal v){
        if (!isGreaterZero(v)){
            return getOppositeNumber(v);
        }
        return v;
    }

    /**
     * 得到该数的负数
     *
     * @param v 需要转换的数字
     * @return {@link BigDecimal }
     * @author yuhh
     * @date 2022-08-10 17:42:00
     */
    public static BigDecimal getNegativeNumber(BigDecimal v){
        if (isGreaterZero(v)){
            return getOppositeNumber(v);
        }
        return v;
    }

    /**
     * 获取非空的BigDecimal对象，为null则返回0
     *
     * @param value 需要判断的值
     * @return {@link BigDecimal } 非空的BigDecimal对象
     * @author yuhh
     * @date 2022-08-10 17:42:06
     */
    public static BigDecimal notNull(BigDecimal value){
        if (value == null) {
            return BigDecimal.ZERO;
        }
        return value;
    }

    /**
     * 获取两个数中比较小的值
     *
     * @param v1 第一个值
     * @param v2 第二个值
     * @return {@link BigDecimal } 比较小的值
     * @author yuhh
     * @date 2022-08-10 17:42:11
     */
    public static BigDecimal getLeast(BigDecimal v1, BigDecimal v2){
        return notNull(v1).compareTo(notNull(v2)) > 0? v2: v1;
    }

    /**
     * 获取两个数中比较大的值
     *
     * @param v1 第一个值
     * @param v2 第二个值
     * @return {@link BigDecimal } 比较大的值
     * @author yuhh
     * @date 2022-08-10 17:42:16
     */
    public static BigDecimal getBigger(BigDecimal v1, BigDecimal v2){
        return notNull(v1).compareTo(notNull(v2)) > 0? v1: v2;
    }

    private BigDecimalUtil(){

    }
}
